VFG.Util=function(){
}
//存放容器
VFG.Util.primitiveMap = new Map();

VFG.Util.getUuid = function() {
	var s = [];
	var hexDigits = "0123456789abcdef";
	for (var i = 0; i < 36; i++) {
		s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
	}
	s[14] = "4"; 
	s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); 
	s[8] = s[13] = s[18] = s[23] = "-";
	var uuid = s.join("");
	return uuid;
};



/**
 * 删除数组
 * index：数组中需要删除数据的起始位置；n：需要删除的元素，数据的个数。
 */
VFG.Util.splice = function(arr,index, n) {
	if(arr){
		arr.splice(index, n);
	}
	return arr;
};
/**
 * 插入
 */
VFG.Util.inset = function(arr,index,data) {
	if(arr){
		arr.splice(index,0,data);
	}
	return arr;
};

/**
 * 替换
 */
VFG.Util.replace = function(arr,n,data) {
	if(arr){
		arr.splice(index,n,data);
	}
	return arr;
};

/**
 * 场景截图
 */
VFG.Util.getSceneImg = function (viewer,width,height) {
	var canvas = viewer.scene.canvas;
    var imageWidth = width?width:800;
    var img = Canvas2Image.convertToImage(canvas, imageWidth, height?height:imageWidth * canvas.height / canvas.width,'png');
    return img.src
}

/**
 * 获取视角
 */
VFG.Util.getVisualAngle=function(viewer) {
	return {
		heading:viewer.camera.heading,
		pitch:viewer.camera.pitch,
		roll:viewer.camera.roll,
		position:viewer.camera.position
	}
};

VFG.Util.removeEntityById=function(viewer,uniqueId) {
	viewer.entities.removeById(uniqueId);
};

VFG.Util.getEntityById=function(viewer,uniqueId) {
	return viewer.entities.getById(uniqueId);
};

VFG.Util.getEntityById=function(viewer,uniqueId) {
	return viewer.entities.getById(uniqueId);
};

VFG.Util.getCenterPoint= function(cartesianA,cartesianB) {
	var _self = this;
	let AtoB = Cesium.Cartesian3.subtract(cartesianA, cartesianB, new Cesium.Cartesian3());
	let cartesian4_1 = Cesium.Cartesian3.divideByScalar(AtoB, 2, new Cesium.Cartesian3())
	let cartesianC= Cesium.Cartesian3.add(cartesian4_1, cartesianB, new Cesium.Cartesian3());
    return cartesianC;
}

/**
 * 经纬度获取屏幕坐标
 */
VFG.Util.getC2FormLnLa = function(viewer,position) {
	return Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,this.getC3FormLnLa(position))
}


/**
 * 经纬度转笛卡尔坐标
 * position:{
 * 	x:经度
 *  y:维度
 *  z:高度
 * }
 */
VFG.Util.getC3FormLnLa = function(position) {
	return Cesium.Cartesian3.fromDegrees(position.x*1,position.y*1,position.z*1);
}

/**
 * 笛卡尔坐标转经纬度
 */
VFG.Util.getLnLaFormC3 = function(viewer,cartesian3) {
	var ellipsoid=viewer.scene.globe.ellipsoid;
	var cartographic=ellipsoid.cartesianToCartographic(cartesian3);
	var lat=Cesium.Math.toDegrees(cartographic.latitude).toFixed(7);
	var lng=Cesium.Math.toDegrees(cartographic.longitude).toFixed(7);
	var alt=cartographic.height.toFixed(2);
	return {
		x:lng,
		y:lat,
		z:alt
	};
}

//
///**
// * 获取鼠标当前的屏幕坐标位置的三维Cesium坐标
// * @param {Cesium.Scene} scene 
// * @param {Cesium.Cartesian2} position 二维屏幕坐标位置
// * @param {Cesium.Entity} noPickEntity 排除的对象（主要用于绘制中，排除对自己本身的拾取）
// */
VFG.Util.getScreenToC3=function(viewer, position, noPickEntity) {
	var scene = viewer.scene;
	var cartesian3;
	if (scene.mode !== Cesium.SceneMode.MORPHING) {
		var pickedObject = scene.pick(position);
		if (scene.pickPositionSupported && Cesium.defined(pickedObject)) {
			if(!this.hasPickedModel(pickedObject,noPickEntity)){
				cartesian3 = viewer.scene.pickPosition(position);
				if (Cesium.defined(cartesian3)) {
				    var height = Cesium.Cartographic.fromCartesian(cartesian3).height;
				    var lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian3).latitude);
				    var lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian3).longitude);
				    return viewer.scene.clampToHeight(cartesian3);
	            }
			}
		}
	}
	
	//获取地形表面的经纬度高程坐标：
	if (!Cesium.defined(cartesian3) &&  (viewer.scene)) {
		var ray = viewer.camera.getPickRay(position);
		if (Cesium.defined(ray)) {
			cartesian3 = viewer.scene.globe.pick(ray, viewer.scene);
			if (Cesium.defined(cartesian3)){
			    var height = Cesium.Cartographic.fromCartesian(cartesian3).height;
			    var lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian3).latitude);
			    var lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian3).longitude);
			    return Cesium.Cartesian3.fromDegrees(lng, lat, height>0?height:0);
			}
		}

	}
	
	//二维坐标，获取椭球体表面的经纬度坐标：
	if (!Cesium.defined(cartesian3)) {
		cartesian3 = viewer.scene.camera.pickEllipsoid(position,viewer.scene.globe.ellipsoid);
		return cartesian3;
	}
	return cartesian3;
}



/**

 * 获取鼠标当前的屏幕坐标位置的三维Cesium坐标

 * @param {Cesium.Scene} scene 

 * @param {Cesium.Cartesian2} position 二维屏幕坐标位置

 * @param {Cesium.Entity} noPickEntity 排除的对象（主要用于绘制中，排除对自己本身的拾取）

 */
//VFG.Util.getScreenToC3=function(viewer, position, noPickEntity) {
//	var _this=this;
//	var scene = viewer.scene;
//    var cartesian;
//    //在模型上提取坐标   
//    var pickedObject;
//    try {
//        pickedObject = scene.pick(position, 5, 5);
//    } catch (e) {
//        console.log("scene.pick 拾取位置时异常");
//    }
//
//    if (scene.pickPositionSupported && Cesium.defined(pickedObject)) {
//        cartesian = scene.pickPosition(position);
//        if (Cesium.defined(cartesian)) {
//            var height = Cesium.Cartographic.fromCartesian(cartesian).height;
//            var lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).latitude);
//            var lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).longitude);
//            console.log(height);
//            return Cesium.Cartesian3.fromDegrees(lng, lat, height>0?height+1:0);
//        }
//    } else {}
//
//        //超图s3m数据拾取
//    if (Cesium.defined(Cesium.S3MTilesLayer)) {
//        cartesian = scene.pickPosition(position);
//        if (Cesium.defined(cartesian)) {
//            var height = Cesium.Cartographic.fromCartesian(cartesian).height;
//            var lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).latitude);
//            var lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).longitude);
//            return Cesium.Cartesian3.fromDegrees(lng, lat, height>0?height+1:0);
//        }
//    }
//
//    //onlyPickModelPosition是在 ViewerEx 中定义的对外属性
//    //通过 viewer.mars.onlyPickModelPosition 进行修改
//    if (scene.onlyPickModelPosition) return cartesian; //只取模型上的时候，不继续读取了
//
//
//    //测试scene.pickPosition和globe.pick的适用场景 https://zhuanlan.zhihu.com/p/44767866
//    //1. globe.pick的结果相对稳定准确，不论地形深度检测开启与否，不论加载的是默认地形还是别的地形数据；
//    //2. scene.pickPosition只有在开启地形深度检测，且不使用默认地形时是准确的。
//    //注意点： 1. globe.pick只能求交地形； 2. scene.pickPosition不仅可以求交地形，还可以求交除地形以外其他所有写深度的物体。
//
//    //提取鼠标点的地理坐标 
//    if (scene.mode === Cesium.SceneMode.SCENE3D) {
//        //三维模式下
//        var pickRay = scene.camera.getPickRay(position);
//        cartesian = scene.globe.pick(pickRay, scene);
//    } else {
//        //二维模式下
//        cartesian = scene.camera.pickEllipsoid(position, scene.globe.ellipsoid);
//    }
//
//    var height = Cesium.Cartographic.fromCartesian(cartesian).height;
//    var lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).latitude);
//    var lng = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).longitude);
//    return Cesium.Cartesian3.fromDegrees(lng, lat, height>0?height+1:0);
//}




/**
 * 模型矩阵转笛卡尔坐标
 */
VFG.Util.modelMatrixToC3=function (modelMatrix){
	var cartesian3=new Cesium.Cartesian3();
	Cesium.Matrix4.getTranslation(modelMatrix,cartesian3);//根据最终变换矩阵m得到p2
	return cartesian3
}

VFG.Util.modelMatrixToRotate=function (modelMatrix){
    var m1 = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Matrix4.getTranslation(modelMatrix, new Cesium.Cartesian3()), Cesium.Ellipsoid.WGS84, new Cesium.Matrix4());
    // 矩阵相除
    var m3 = Cesium.Matrix4.multiply(Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()), modelMatrix, new Cesium.Matrix4());
    // 得到旋转矩阵
    var mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3());
    // 计算四元数
    var q = Cesium.Quaternion.fromRotationMatrix(mat3);
    // 计算旋转角(弧度)
    var hpr = Cesium.HeadingPitchRoll.fromQuaternion(q);
    // 得到角度
    var heading = Cesium.Math.toDegrees(hpr.heading).toFixed(2)*1;;
    var pitch = Cesium.Math.toDegrees(hpr.pitch).toFixed(2)*1;;
    var roll = Cesium.Math.toDegrees(hpr.roll).toFixed(2)*1;;
    if(heading<0){
    	heading+=360;
    }
    if(pitch<0){
    	pitch+=360;
    }
    if(roll<0){
    	roll+=360;
    }
	return {x:pitch,y:heading,z:roll}
}


VFG.Util.modelMatrixToHeadingPitchRoll=function (modelMatrix){
    var m1 = Cesium.Transforms.eastNorthUpToFixedFrame(Cesium.Matrix4.getTranslation(modelMatrix, new Cesium.Cartesian3()), Cesium.Ellipsoid.WGS84, new Cesium.Matrix4());
    // 矩阵相除
    var m3 = Cesium.Matrix4.multiply(Cesium.Matrix4.inverse(m1, new Cesium.Matrix4()), modelMatrix, new Cesium.Matrix4());
    // 得到旋转矩阵
    var mat3 = Cesium.Matrix4.getMatrix3(m3, new Cesium.Matrix3());
    // 计算四元数
    var q = Cesium.Quaternion.fromRotationMatrix(mat3);
    // 计算旋转角(弧度)
    var headingPitchRoll = Cesium.HeadingPitchRoll.fromQuaternion(q);
	return headingPitchRoll;
}

/**
 * 判断是否包含本身
 */
VFG.Util.hasPickedModel=function(pickedObject, noPickEntity) {
    if (Cesium.defined(pickedObject.id)) {
        //entity 
        var entity = pickedObject.id;
        if (entity._noMousePosition) return entity; //排除标识不拾取的对象
        if (noPickEntity && entity == noPickEntity) return entity;
    }

    if (Cesium.defined(pickedObject.primitive)) {
        var primitive = pickedObject.primitive;
        if (primitive._noMousePosition) return primitive; //排除标识不拾取的对象
        if (noPickEntity && primitive == noPickEntity) return primitive;
    }
    return null;
}

VFG.Util.getScreenToLnLa  = function(viewer, position,noPickEntity) {
	var cartesian3=VFG.Util.getScreenToC3(viewer, position, noPickEntity);
	if(Cesium.defined(cartesian3)){
		return VFG.Util.getLnLaFormC3(viewer,cartesian3);
	}
	return null;
}

/**
 * 经纬度转笛卡尔坐标
 */
VFG.Util.getC3ToLnLa  = function(viewer, cartesian3) {
	var ellipsoid=viewer.scene.globe.ellipsoid;
	var cartographic=ellipsoid.cartesianToCartographic(cartesian3);
	var lat=Cesium.Math.toDegrees(cartographic.latitude);
	var lng=Cesium.Math.toDegrees(cartographic.longitude);
	var height=cartographic.height;
	return {x:lng,y:lat,z:height};
}

/**
 * 屏幕坐标
 */
VFG.Util.getCartesian2 = function(x,y) {
	var _this=this;
	if(Cesium.defined(x) && Cesium.defined(y) ){
		return new Cesium.Cartesian2(x*1,y*1)
	}
	return null;
};

/**
 * 笛卡尔坐标
 */
VFG.Util.getCartesian3 = function(x,y,z) {
	var _this=this;
	if(Cesium.defined(x) && Cesium.defined(y) && Cesium.defined(z)){
		return new Cesium.Cartesian3(x*1,y*1,z*1)
	}
	return null;
};

VFG.Util.getDistanceDisplayCondition = function(x,y) {
	var _this=this;
	if(Cesium.defined(x) && Cesium.defined(y) ){
		return new Cesium.DistanceDisplayCondition(x*1,y*1)
	}
	return null;
};
VFG.Util.getNearFarScalar = function(near, nearValue, far, farValue) {
	var _this=this;
	if(Cesium.defined(near) && Cesium.defined(nearValue) && Cesium.defined(far) && Cesium.defined(farValue)){
		return new Cesium.NearFarScalar(near*1, nearValue*1, far*1, farValue*1);
	}
	return null;
};

VFG.Util.getHorizontalOrigin = function(value){
	if("0"===value){
		return  Cesium.HorizontalOrigin.CENTER ;
	}
	else if("1"===value){
		return  Cesium.HorizontalOrigin.LEFT  ;
	}
	else if("2"===value){
		return  Cesium.HorizontalOrigin.RIGHT  ;
	}
	else{
		return  Cesium.HorizontalOrigin.CENTER;
	}
} 
VFG.Util.getHeightReference = function(value){
	if("0"===value){
		return  Cesium.HeightReference.NONE ;
	}
	else if("1"===value){
		return  Cesium.HeightReference.CLAMP_TO_GROUND  ;
	}
	else if("2"===value){
		return  Cesium.HeightReference.RELATIVE_TO_GROUND  ;
	}
	else{
		return  Cesium.HorizontalOrigin.NONE;
	}
}	
VFG.Util.getVerticalOrigin = function(value){
	if("0"===value){
		return  Cesium.VerticalOrigin.BASELINE;
	}
	else if("1"===value){
		return  Cesium.VerticalOrigin.BOTTOM ;
	}
	else if("2"===value){
		return  Cesium.VerticalOrigin.CENTER ;
	}
	else if("3"===value){
		return  Cesium.VerticalOrigin.VerticalOrigin;
	}else{
		return  Cesium.VerticalOrigin.BASELINE;
	}
}

VFG.Util.getEntityForLine = function(data) {
	if(!data){
		return null;
	}
    var distanceDisplayCondition =VFG.Util.getDistanceDisplayCondition(data.distanceDisplayConditionX,data.distanceDisplayConditionY);
    var material=VFG.Util.getMaterialForLine(data);
    if(!material){
		return null;
	}
    
    return{
        show: true,
        positions: data.positions?data.positions:[],
		width : data.width*1,
		loop:data.loop&&data.loop=='1'?true:false,
		clampToGround:data.clampToGround&&data.clampToGround=='1'?true:false,
		material:material?material:Cesium.Color.RED,
		distanceDisplayCondition : distanceDisplayCondition?distanceDisplayCondition:undefined,
		zIndex: data.sort*1,		
	}
};

VFG.Util.getMaterialForLine = function(style,ctx){
	var _this=this;
	if(Cesium.defined(style)){
		if(style.materialType=="solid"){
			return (style.color)?Cesium.Color.fromCssColorString(style.color):Cesium.Color.RED;//线条颜色;
		}
		else if(style.materialType=="dash"){
			return new Cesium.PolylineDashMaterialProperty({
				color:(style.color)?Cesium.Color.fromCssColorString(style.color):Cesium.Color.RED,//线条颜色
				gapColor:(style.gapColor)?Cesium.Color.fromCssColorString(style.gapColor):Cesium.Color.WHITE,//间隔颜色
				dashLength:(style.dashLength)?style.dashLength*1:16,//间隔距离
				dashPattern:(style.dashPattern)?style.dashPattern*1:255.0
			})
		}
		else if(style.materialType=="outline"){
			return new Cesium.PolylineOutlineMaterialProperty({
				color:(style.color)?Cesium.Color.fromCssColorString(style.color):Cesium.Color.RED,//线条颜色
				outlineWidth: (style.outlineWidth)?style.outlineWidth*1:5,
				outlineColor:(style.outlineColor)?Cesium.Color.fromCssColorString(style.outlineColor):Cesium.Color.WHITE,//线条颜色
			});
		}
		else if(style.materialType=="glow"){
			return new Cesium.PolylineGlowMaterialProperty({
					color:(style.color)?Cesium.Color.fromCssColorString(style.color):Cesium.Color.RED,//线条颜色
					glowPower: (style.glowPower)?style.glowPower*1:0.5,//发光强度
				});
		}
		else if(style.materialType=="arrow"){
			return new Cesium.PolylineArrowMaterialProperty(
					(style.color)?Cesium.Color.fromCssColorString(style.color):Cesium.Color.RED
			);
		}
		else if(style.materialType=="od"){
			return new Cesium.ODLineMaterial(
					(style.color)?Cesium.Color.fromCssColorString(style.color):Cesium.Color.RED,style.interval?style.interval*1000:20000,style.direction,style.effect,ctx+"/"+style.imageUrl)
		}
		else{
			return Cesium.Color.BLUE;
		}
	}
}

VFG.Util.getEntityForPolygon = function(data) {
	var _this=this;
	var distanceDisplayCondition =VFG.Util.getDistanceDisplayCondition(data.distanceDisplayConditionX*1,data.distanceDisplayConditionY*1);
	
	var options={
		stRotation:data.stRotation?data.stRotation:0.0,
		fill:data.fill?data.fill:false,
		material:data.color? Cesium.Color.fromCssColorString(data.color):Cesium.Color.BLACK,
		outline:data.outline && data.outline=='1'  ?true:false,
		outlineColor:data.outlineColor? Cesium.Color.fromCssColorString(data.outlineColor):Cesium.Color.BLACK,
		outlineWidth:data.outlineWidth?data.outlineWidth*1:0.0,
		closeTop:data.closeTop?data.closeTop:false,
		closeBottom:data.closeBottom?data.closeBottom:false,
		arcType:Cesium.ArcType.GEODESIC,
		shadows:data.shadows?data.shadows:false,
		distanceDisplayCondition:distanceDisplayCondition||null,
		classificationType:_this.getClassificationType(data.classificationType)
	}
	
	var perPositionHeight=data.perPositionHeight && data.perPositionHeight=='1'  ?true:false;
	if(perPositionHeight){
		 options.height=data.height?data.height:0.0;
		 options.perPositionHeight=perPositionHeight;
		 options.heightReference=_this.getHeightReference(data.heightReference);
		 options.extrudedHeight=data.extrudedHeight?data.extrudedHeight:0.0;
		 options.extrudedHeightReference=_this.getHeightReference(data.extrudedHeightReference);
	}
	return options;
};

VFG.Util.getClassificationType = function(value) {
	if('1'==value){
		return Cesium.ClassificationType.TERRAIN;
	}
	else if('2'==value){
		return Cesium.ClassificationType.CESIUM_3D_TILE;
	}else{
		return Cesium.ClassificationType.BOTH;
	}
};

/**
 * 创建线段
 */
VFG.Util.createLinePrimitive=function(viewer,ops,polyline){
	if(polyline){
		return primitive =viewer.entities.add({
        	id:ops.id,
        	name:ops.name||'线',
        	show: true,
        	bizType:ops.code||'',
            polyline: polyline
        });
	}else{
		return primitive =viewer.entities.add({
        	id:ops.id,
        	name:ops.name||'线',
        	bizType:ops.code||'',
            polyline: {
                show: true,
                positions:ops.positions||[],
                material:Cesium.Color.RED,
                width:2
            }
        });
	}
}

/***
 * 创建多边形
 */
VFG.Util.createPolygonPrimitive=function(viewer,ops,polygon){
	viewer.entities.removeById(ops.id);
	if(polygon){
		return viewer.entities.add({
        	id:ops.id,
        	name:ops.name||'多边形',
        	show: true,
        	polygon: polygon
        });
	}else{
		return viewer.entities.add({
        	id:ops.id,
        	name:ops.name||'多边形',
        	show: true,
            polygon:{
                hierarchy : ops.hierarchy||[],
                perPositionHeight: true,
                material: Cesium.Color.RED.withAlpha(0.7),
                outline: true,
                outlineColor: Cesium.Color.YELLOW.withAlpha(1)
            }
        });
	}
}

VFG.Util.getHeightReference=function(value){
	if('RELATIVE_TO_GROUND'==value){
		return Cesium.HeightReference.RELATIVE_TO_GROUND;
	}
	else if('CLAMP_TO_GROUND'==value){
		return Cesium.HeightReference.CLAMP_TO_GROUND;
	}else{
		return Cesium.HeightReference.NONE;
	}
}

/**
 * 创建模型ForGLTF
 */
VFG.Util.createGltfPrimitive=function(viewer,ops){
	if(!ops){
		console.log('参数必填!!!');
		return;
	}
	
	if(!ops.uri){
		console.log('模型地址必填!!!');
		return;
	}
	
	if('GLTF'!=ops.type){
		console.log('模型格式必需是GLTF!!!');
		return;
	}
	if(!(ops.posX && ops.posY && ops.posZ)){
		console.log('坐标必填!!!');
		return;
	}
	if(!this.primitiveMap.has(ops.id)){
		var heading = Cesium.defaultValue(ops.heading, 0.0);
	    var pitch = Cesium.defaultValue(ops.pitch, 0.0);
	    var roll = Cesium.defaultValue(ops.roll, 0.0);
	    var headingPitchRoll = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(heading), Cesium.Math.toRadians(pitch), Cesium.Math.toRadians(roll));
		var distanceDisplayCondition =VFG.Util.getDistanceDisplayCondition(ops.displayNear,ops.displayFar);
		var origin = Cesium.Cartesian3.fromDegrees(ops.posX*1, ops.posY*1,ops.posZ*1);
		var modelMatrix =Cesium.Transforms.headingPitchRollToFixedFrame(origin, headingPitchRoll, Cesium.Ellipsoid.WGS84, Cesium.Transforms.eastNorthUpToFixedFrame, new Cesium.Matrix4());
		var model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
			id:ops.id,
			name:ops.name||'未命名',
			url: ops.uri,
			type:ops.type,
			bizType:ops.code||'',
			show : ( ops.show &&  ops.show!='1')?false : true,                     
			modelMatrix : modelMatrix,
			scale: ops.scale*1||1,
			minimumPixelSize:(ops.minimumPixelSize)?ops.minimumPixelSize*1:0,
			maximumScale:(ops.minimumPixelSize)?ops.minimumPixelSize*1:undefined,
			allowPicking : true,        
			debugShowBoundingVolume : false, 
			debugWireframe : false,
			distanceDisplayCondition:distanceDisplayCondition?distanceDisplayCondition:undefined,
		}));
		model.readyPromise.then(function(model) {
		  model.activeAnimations.addAll();
		}).otherwise(function(error){
	    });
		this.primitiveMap.set(ops.id,model);
		return model;
	}else{
		return this.primitiveMap.get(ops.id);
	}
	
/*    var distanceDisplayCondition =VFG.Util.getDistanceDisplayCondition(ops.displayNear,ops.displayFar);
	var position = Cesium.Cartesian3.fromDegrees(ops.posX*1, ops.posY*1,ops.posZ*1)
	var entity=new Cesium.Entity({
		id:ops.id,
    	name:ops.name||'未命名',
	    show: true,
	    position: position,
	    orientation:Cesium.Transforms.headingPitchRollQuaternion(
    		 position,
	         new Cesium.HeadingPitchRoll(
	            Cesium.Math.toRadians(ops.heading*1||0), 
	            Cesium.Math.toRadians(ops.pitch*1||0),
	            Cesium.Math.toRadians(ops.roll*1||0)
			 )
	    ),
	    model:{
	    	uri: ops.uri,
	    	basePath: ops.basePath||'',
	    	scale: ops.scale*1||1,
	    	allowPicking:(ops.allowPicking && ops.allowPicking=='1')?true:false,
			minimumPixelSize:(ops.minimumPixelSize)?ops.minimumPixelSize*1:0,
			maximumScale:(ops.minimumPixelSize)?ops.minimumPixelSize*1:undefined,
		    distanceDisplayCondition:distanceDisplayCondition?distanceDisplayCondition:undefined,
		    HeightReference:this.getHeightReference(ops.heightReference)
	    }
	});*/
	//return viewer.entities.add(entity)
}

VFG.Util.getPrimitiveModelMatrix=function(ops){
    var ry = Cesium.defaultValue(ops.ry, 0.0);
    var rx = Cesium.defaultValue(ops.rx, 0.0);
    var rz = Cesium.defaultValue(ops.rz, 0.0);
    
    var transformPosition =Cesium.Cartesian3.fromDegrees(ops.x*1, ops.y*1,ops.z*1);
    var matrix = Cesium.Transforms.eastNorthUpToFixedFrame(transformPosition);
    var scale = Cesium.Matrix4.fromUniformScale(ops.scale*1);
    Cesium.Matrix4.multiply(matrix, scale, matrix);
    
    var rotationX = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(rx));
    var rotationY = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(ry));
    var rotationZ = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(rz));
    
    
    var rotationTranslationX = Cesium.Matrix4.fromRotationTranslation(rotationX);
    var rotationTranslationY = Cesium.Matrix4.fromRotationTranslation(rotationY);
    var rotationTranslationZ = Cesium.Matrix4.fromRotationTranslation(rotationZ);
    Cesium.Matrix4.multiply(matrix, rotationTranslationX, matrix);
    Cesium.Matrix4.multiply(matrix, rotationTranslationY, matrix);
    Cesium.Matrix4.multiply(matrix, rotationTranslationZ, matrix);
	return matrix;
}


VFG.Util.updatePrimitiveModelMatrix=function(ops){
	var heading = Cesium.defaultValue(ops.heading, 0.0);
	var pitch = Cesium.defaultValue(ops.pitch, 0.0);
	var roll = Cesium.defaultValue(ops.roll, 0.0);
    //旋转
   var mx = Cesium.Matrix3.fromRotationX(pitch);
   var my = Cesium.Matrix3.fromRotationY(heading);
   var mz = Cesium.Matrix3.fromRotationZ(roll);
   var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
   var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
   var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
   //平移
   var origin = Cesium.Cartesian3.fromDegrees(ops.posX*1, ops.posY*1,ops.posZ*1);
   var m = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
   //旋转、平移矩阵相乘
   Cesium.Matrix4.multiply(m, rotationX, m);
   Cesium.Matrix4.multiply(m, rotationY, m);
   Cesium.Matrix4.multiply(m, rotationZ, m);
   return m;
}

VFG.Util.create3DTilePrimitive=function(viewer,ops){
	if(!ops){
		console.log('参数必填!!!');
		return;
	}
	
	if(!ops.uri){
		console.log('模型地址必填!!!');
		return;
	}
	
	if('3DTILES'!=ops.type){
		console.log('模型格式必需是3DTILES!!!');
		return;
	}
	
	
	if(!this.primitiveMap.has(ops.id)){
		var primitive=viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
			id : ops.id,
			url : ops.uri,
			name : ops.name ||'未命名',
			show : ( ops.show &&  ops.show!='1')?false : true,    
			bizType:ops.code||'',
			preferLeaves:(ops && ops.preferLeaves && ops.preferLeaves=='1')?true:false,
			imageBasedLightingFactor :Cesium.Cartesian2(1.0, 1.0),
			loadSiblings:true,
			skipLevels:ops.skipLevels ? ops.skipLevels*1: 1,
			baseScreenSpaceError:ops.baseScreenSpaceError ? ops.baseScreenSpaceError*1: 1024,
			skipScreenSpaceErrorFactor:ops.skipScreenSpaceErrorFactor ? ops.skipScreenSpaceErrorFactor*1: 16,
			maximumMemoryUsage:ops.maximumMemoryUsage ? ops.maximumMemoryUsage*1: 512,
			maximumScreenSpaceError : ops.maximumScreenSpaceError ? ops.maximumScreenSpaceError*1: 16,
			skipLevelOfDetail : ops.skipLevelOfDetail ? (ops.skipLevelOfDetail=='on'?true:false): false,
			maximumNumberOfLoadedTiles : ops.maximumNumberOfLoadedTiles ? ops.maximumNumberOfLoadedTiles*1: 1024, //最大加载瓦片个数			
		}));
		
		primitive.readyPromise.then(function(tileset) {

			if(ops.posX && ops.posY && ops.posZ){
				  tileset._root.transform = VFG.Util.getPrimitiveModelMatrix(ops);
			}else{
	            var heightOffset =ops.z || 0;  //高度
	            var boundingSphere = tileset.boundingSphere; 
	            var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
	            var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
	            var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
	            var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
	            tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
			}
			
			
		    if(ops.callBack){
		    	var result=VFG.Util.getCenterForModel(tileset,tileset._root.transform);
		    	ops.callBack(result);
		    }
			
		}).otherwise(function(error){
			console.log(error);
	    });
		this.primitiveMap.set(ops.id,primitive);
		return primitive;
	}else{
		return this.primitiveMap.get(ops.id);
	}
}

//获取模型的中心点信息
VFG.Util.getCenterForModel=function(tileset, transform) {
    var result = {};

    //记录模型原始的中心点
    var boundingSphere = tileset.boundingSphere;
    var position = boundingSphere.center;
    var catographic = Cesium.Cartographic.fromCartesian(position);

    var height = Number(catographic.height.toFixed(2));
    var longitude = Number(Cesium.Math.toDegrees(catographic.longitude).toFixed(6));
    var latitude = Number(Cesium.Math.toDegrees(catographic.latitude).toFixed(6));
    result = { x: longitude, y: latitude, z: height };

    //console.log("模型内部原始位置:" + JSON.stringify(result));

    //如果tileset自带世界矩阵矩阵，那么计算放置的经纬度和heading
    if (transform) {
        var matrix = Cesium.Matrix4.fromArray(tileset._root.transform);
        var pos = Cesium.Matrix4.getTranslation(matrix, new Cesium.Cartesian3());
        var wpos = Cesium.Cartographic.fromCartesian(pos);
        if (Cesium.defined(wpos)) {
            result.x = Number(Cesium.Math.toDegrees(wpos.longitude).toFixed(6));
            result.y = Number(Cesium.Math.toDegrees(wpos.latitude).toFixed(6));
            result.z = Number(wpos.height.toFixed(2));

            //取旋转矩阵
            var rotmat = Cesium.Matrix4.getMatrix3(matrix, new Cesium.Matrix3());
            //默认的旋转矩阵
            var defrotmat = Cesium.Matrix4.getMatrix3(Cesium.Transforms.eastNorthUpToFixedFrame(pos), new Cesium.Matrix3());

            //计算rotmat 的x轴，在defrotmat 上 旋转
            var xaxis = Cesium.Matrix3.getColumn(defrotmat, 0, new Cesium.Cartesian3());
            var yaxis = Cesium.Matrix3.getColumn(defrotmat, 1, new Cesium.Cartesian3());
            var zaxis = Cesium.Matrix3.getColumn(defrotmat, 2, new Cesium.Cartesian3());

            var dir = Cesium.Matrix3.getColumn(rotmat, 0, new Cesium.Cartesian3());

            dir = Cesium.Cartesian3.cross(dir, zaxis, dir);
            dir = Cesium.Cartesian3.cross(zaxis, dir, dir);
            dir = Cesium.Cartesian3.normalize(dir, dir);

            var heading = Cesium.Cartesian3.angleBetween(xaxis, dir);

            var ay = Cesium.Cartesian3.angleBetween(yaxis, dir);

            if (ay > Math.PI * 0.5) {
                heading = 2 * Math.PI - heading;
            }
            result.rotation_x = 0;
            result.rotation_y = 0;
            result.rotation_z = Number(Cesium.Math.toDegrees(heading).toFixed(1));

            result.heading = result.rotation_z; //兼容v1老版本

           // console.log("模型内部世界矩阵:" + JSON.stringify(result));
        }
    }

    return result;
}

VFG.Util.getPrimitiveById=function(viewer,id){
	if(this.primitiveMap.has(id)){
		return this.primitiveMap.get(id);
	}
	return null;
}

VFG.Util.removePrimitive=function(viewer,id){
	if(this.primitiveMap.has(id)){
		if(viewer.scene.primitives.remove(this.primitiveMap.get(id))){
			this.primitiveMap.delete(id);
			return true;
		}
		return false;
	}else{
		return false;	
	}
	return false;
}

VFG.Util.removeAllPrimitive=function(viewer){
	this.primitiveMap.clear();
	return viewer.scene.primitives.removeAll();
}

/**
 * 移除场景元素
 * viewer
 * ops:{id:图层Id,type:图层类型}
 */
VFG.Util.removeScenePrimitive=function(viewer,ops){
	if('point'==ops.type){
		VFG.Point.removePointById(ops.id) 
	}
	else if('line'==ops.type){
		VFG.Util.removeEntityById(viewer,ops.id) 
	}
	else if('polygon'==ops.type){
		VFG.Util.removeEntityById(viewer,ops.id) 
	}
	if('Feature'==ops.type){
		VFG.Model.Feature.removeFeatureById(ops.id) 
	}
	else if('map'==ops.type){
		VFG.Provider.removeById(viewer,ops.id)
	}
	else if('terrain'==ops.type){
		VFG.Provider.removeTerrainProviderById(viewer,ops.id);
	}
	else if('division'==ops.type){
		VFG.Provider.removeById(viewer,ops.id)
	}
	else if('road'==ops.type){
		VFG.Provider.removeById(viewer,ops.id)
	}
	else if('GLTF'==ops.type){
		VFG.Util.removePrimitive(viewer,ops.id);
	}
	else if('3DTILES'==ops.type){
 		VFG.Util.removePrimitive(viewer,ops.id);
	}
}

/**
 * 显示隐藏
 */
VFG.Util.showScenePrimitive=function(viewer,ops){
	if('point'==ops.type){
		var entity=VFG.Point.getPointById(ops.id);
		if(entity){
			entity.show=ops.show;
		}
	}
	else if('line'==ops.type || 'polygon'==ops.type){
		var entity=viewer.entities.getById(ops.id);
		if(entity){
			entity.show=ops.show;
		}
	}
	else if('GLTF'==ops.type || '3DTILES'==ops.type){
		if(this.primitiveMap.has(ops.id)){
			this.primitiveMap.get(ops.id).show=ops.show;
		}
	}
}


VFG.Util.c3sToLnLas=function(viewer,positions){
	var LnLas=[];
	for(var i=0;i<positions.length;i++){
		LnLas.push(this.getC3ToLnLa(viewer,positions[i]));
	}
	return LnLas;
}

VFG.Util.polygonForCreate=function(viewer,polygonRender){
	var _this=this;
	if(!polygonRender){
		return;
	}
	var polygon=polygonRender.polygon;
	var styles=polygonRender.styles;
	if(!polygon){
		return;
	}
	var polygonStyle;
	if(polygon!=null && styles.length>0){
		polygonStyle=VFG.Util.getEntityForPolygon(styles[0]);
	}
	var entity=VFG.Util.getEntityById(viewer,polygon.id);
	if(entity){
		VFG.Util.removeEntityById(viewer,polygon.id);
	}
	var points=[];
	if(polygon.points){
		points=JSON.parse(polygon.points);
		if(points.length>=2){
			var arrForC3=[];
			for(var i=0;i<points.length;i++){
				arrForC3.push(Cesium.Cartesian3.fromDegrees(points[i].x*1,points[i].y*1,points[i].z*1));
			}
			if(polygonStyle){
				polygonStyle.hierarchy=new Cesium.PolygonHierarchy(arrForC3)
				polygonStyle.clampToGround= true //开启贴地
			}
			
			VFG.Util.createPolygonPrimitive(viewer,{
				id:polygon.id,
				name:polygon.name||'',
				hierarchy:new Cesium.PolygonHierarchy(arrForC3)
			},polygonStyle);
		}

	}else{
		console.log('无效数据polygon');
	}
}

//线
VFG.Util.polyLineForCreate=function(viewer,polyLineRender){
	var _this=this;
	if(!polyLineRender){
		return;
	}
	var line=polyLineRender.line;
	var styles=polyLineRender.styles;
	if(!line){
		return;
	}
	var lineStyle;
	if(line!=null && styles.length>0){
		lineStyle=VFG.Util.getEntityForLine(styles[0]);
	}
	var entity=VFG.Util.getEntityById(viewer,line.id);
	if(entity){
		VFG.Util.removeEntityById(viewer,line.id);
	}
	if(line.points){
		var points=JSON.parse(line.points);
		var arrForC3=[];
		for(var i=0;i<points.length;i++){
			arrForC3.push(Cesium.Cartesian3.fromDegrees(points[i].x*1,points[i].y*1,points[i].z*1));
		}
		
		if(lineStyle){
			lineStyle.positions=arrForC3;
		}
		VFG.Util.createLinePrimitive(viewer,{
			id:line.id,
			name:line.name,
			code:line.code||'',
			positions:arrForC3
		},lineStyle);
	}else{
		console.log('无效数据line');
	}
}

/**
 * 获取多边形中心位置
 */
VFG.Util.getCenterForPolygon=function(viewer,positions, height) {
    try {
        if (positions.length == 1) {
            return positions[0];
        } else if (positions.length == 2) {
            return Cesium.Cartesian3.midpoint(positions[0], positions[1], new Cesium.Cartesian3());
        }
        
        var LnLas=[];
        var points=[];
        for(var i=0;i<positions.length;i++){
        	var lnla=this.getC3ToLnLa(viewer, positions[i]);
        	LnLas.push(lnla);
        	points.push([lnla.x,lnla.y]);
        }
        points.push(points[0]);
        var ds=[points]
        var polygon = turf.polygon(ds);
        var center = turf.centerOfMass(polygon);
        var coordinates=center.geometry.coordinates;
        var cartesian3=new Cesium.Cartesian3.fromDegrees(coordinates[0],coordinates[1],0);
    	var cartesian2=Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,cartesian3);
    	if (viewer.scene.mode !== Cesium.SceneMode.MORPHING) {
    		var pickedObject = viewer.scene.pick(cartesian2);
    		if (viewer.scene.pickPositionSupported && pickedObject) {
    			var carto=new Cesium.Cartographic.fromDegrees(coordinates[0],coordinates[1])
    			var sampleHeight = viewer.scene.sampleHeight(carto);
    			return new Cesium.Cartesian3.fromDegrees(coordinates[0],coordinates[1],sampleHeight);
    		}else{
    			var carto=new Cesium.Cartographic.fromDegrees(coordinates[0],coordinates[1])
        		var heightTerrain =  viewer.scene.globe.getHeight(carto);
    			return new Cesium.Cartesian3.fromDegrees(coordinates[0],coordinates[1],heightTerrain);
    		}
    	}else{
			var carto=new Cesium.Cartographic.fromDegrees(coordinates[0],coordinates[1])
    		var heightTerrain =  viewer.scene.globe.getHeight(carto);
			return new Cesium.Cartesian3.fromDegrees(coordinates[0],coordinates[1],heightTerrain);
    	}
    } catch (e) {
    	console.log(e);
        return positions[Math.floor(positions.length / 2)];
    }
}

/**

 * 获取坐标数组中最高高程值
 * @param {Array} positions Array<Cartesian3> 笛卡尔坐标数组
 * @param {Number} defaultVal 默认高程值

 */
VFG.Util.getMaxHeight=function(positions, defaultVal) {
    if (defaultVal == null) defaultVal = 0;
    var maxHeight = defaultVal;
    if (positions == null || positions.length == 0) return maxHeight;
    for (var i = 0; i < positions.length; i++) {
        var tempCarto = Cesium.Cartographic.fromCartesian(positions[i]);
        if (tempCarto.height > maxHeight) {
            maxHeight = tempCarto.height;
        }
    }
    return formatNum(maxHeight, 2);
}

//格式化 数字 小数位数
VFG.Util.formatNum=function(num, digits) {
    return Number(num.toFixed(digits || 0));
}

/**
 * 获取高度
 */
VFG.Util.getSurfaceHeight=function (viewer, position, opts) {
	var _this=this;
	var cartesian2=Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene,position);
	if (viewer.scene.mode !== Cesium.SceneMode.MORPHING && cartesian2) {
		var pickedObject = viewer.scene.pick(cartesian2);
		if (viewer.scene.pickPositionSupported && Cesium.defined(pickedObject)) {
			return _this.getSurface3DTilesetHeight(viewer, position, opts);
		}
	}
	return _this.getSurfaceTerrainHeight(viewer, position, opts);
}

//
///**
//
// * 获取坐标的 贴模型高度
// * opts支持:   是否异步 asyn:true  异步回调方法calback返回“新高度”和“原始的Cartographic坐标”
// */
//VFG.Util.getSurface3DTilesHeight=function(scene, position, opts) {
//	var _this=this;
//    opts = opts || {};
//    //原始的Cartographic坐标
//    opts.cartesian = opts.cartesian || Cesium.Cartographic.fromCartesian(position);
//    var carto = opts.cartesian;
//
//    //是否异步求精确高度 
//    if (opts.asyn) {
//    	 var cartographic=Cesium.Cartographic.fromCartesian(position);
//        scene.sampleHeightMostDetailed([cartographic]).then(function (clampedPositions) {
//            var clampedPt = clampedPositions[0];
//            if (Cesium.defined(clampedPt)) {
//                var heightTiles = clampedPt.height;
//                if (Cesium.defined(heightTiles) && heightTiles > -1000) {
//                    if (opts.calback) opts.calback(heightTiles, clampedPt);
//                    return;
//                }
//            }else{
//            	_this.getSurfaceTerrainHeight(scene, position, opts);
//            }
//        });
//    } else {
//        //取贴模型高度
//        var heightTiles = scene.sampleHeight(carto);
//        if (Cesium.defined(heightTiles) && heightTiles > -1000) {
//            if (opts.calback) opts.calback(heightTiles, carto);
//            return heightTiles;
//        }
//    }
//    return 0; //表示取值失败
//}

/**
 * 获取坐标的 贴地高度
 * opts支持:   是否异步 asyn:true  异步回调方法calback
 */
//VFG.Util.getSurfaceTerrainHeight=function(scene, position, opts) {
//    opts = opts || {};
//    //原始的Cartographic坐标
//    var carto = opts.cartesian || Cesium.Cartographic.fromCartesian(position);
//    var _hasTerrain = VFG.Provider.hasTerrain; //是否有地形
//    if (!_hasTerrain) {
//        //不存在地形，直接返回
//        if (opts.calback) opts.calback(carto.height, carto);
//        return carto.height;
//    }
//
//    //是否异步求精确高度 
//    if (opts.asyn) {
//        Cesium.when(Cesium.sampleTerrainMostDetailed(scene.terrainProvider, [carto]), function (samples) {
//            var clampedCart = samples[0];
//            var heightTerrain;
//            if (Cesium.defined(clampedCart) && Cesium.defined(clampedCart.height)) {
//                heightTerrain = clampedCart.height;
//            } else {
//                heightTerrain = scene.globe.getHeight(carto);
//            }
//            if (opts.calback) opts.calback(heightTerrain, carto);
//        });
//    } else {
//        var heightTerrain = scene.globe.getHeight(carto);
//        if (Cesium.defined(heightTerrain) && heightTerrain > -1000) {
//            if (opts.calback) opts.calback(heightTerrain, carto);
//            return heightTerrain;
//        }
//    }
//    return 0; //表示取值失败
//}

/**
 * 获取模型表面高度
 * viewer:
 * cartesian3:笛卡尔坐标
 * opts:{
 * 	asyn:true/false
 * 	calback(e)：e模型表面高度
 * }
 */
VFG.Util.getSurfaceModelHeight=function(viewer, cartesian3, opts) {
	var cartographic=Cesium.Cartographic.fromCartesian(cartesian3);
	if (Cesium.defined(cartographic)){
		  var objectsToExclude = [cartographic];
		  var height;
		  if (viewer.scene.sampleHeightSupported) {
			  if (opts.asyn){
				  viewer.scene.sampleHeightMostDetailed(objectsToExclude).then(function(updatedPosition) {
					  height= positions[0].height;
					  if (Cesium.defined(height)){
						  if (opts.calback) {
							  opts.calback(height);
						  }
					  }else{
						  if (opts.calback) {
							  opts.calback(0);
						  } 
					  }
				  });
			  }else{
				  height = viewer.scene.sampleHeight(cartographic, objectsToExclude);
				  if (Cesium.defined(height)){
					  return height;
				  }
			  }
		  }
	}
	return 0;
}

/**
 * 获取3DTileset表面高度
 * cartesian3 笛卡尔坐标
 */
VFG.Util.getSurface3DTilesetHeight=function(viewer, cartesian3, opts) {
	var _this=this;
	if(Cesium.defined(cartesian3)){
		if (viewer.scene.clampToHeightSupported){
			if (opts && opts.asyn){
				viewer.scene.clampToHeightMostDetailed([cartesian3]).then(function(clampedCartesians) {
					var clampedPt = clampedCartesians[0];
		            if (Cesium.defined(clampedPt)) {
		                var heightTiles = Cesium.Cartographic.fromCartesian(clampedPt).height;
		                if (Cesium.defined(heightTiles) && heightTiles > -1000) {
		                	if (opts.calback) opts.calback(heightTiles);
		                }else{
		                	_this.getSurfaceTerrainHeight(viewer, cartesian3, opts);
		                }
		            }else{
		            	_this.getSurfaceTerrainHeight(viewer, cartesian3, opts);
		            }
				});
			}else{
				var c3=viewer.scene.clampToHeight(cartesian3);
				if (Cesium.defined(c3)){
					var LnLa=VFG.Util.getC3ToLnLa(viewer, c3);
					if(Cesium.defined(LnLa) &&  LnLa.z>-1000){
						return LnLa.z;
					}else{
					 _this.getSurfaceTerrainHeight(viewer, cartesian3, opts);
					}
				}
			}
		}else{
			_this.getSurfaceTerrainHeight(viewer, cartesian3, opts);
		}
	}
}

/**
 * 获取地表高度
 */
VFG.Util.getSurfaceTerrainHeight=function(viewer, cartesian3, opts) {
	if (Cesium.defined(viewer.scene.terrainProvider)){
		var cartographic=Cesium.Cartographic.fromCartesian(cartesian3);
		if (Cesium.defined(cartographic)){
			  var _hasTerrain = VFG.Provider.hasTerrain; //是否有地形
			  if (!_hasTerrain) {
			      if (opts.calback) opts.calback(cartographic.height);
			      return cartographic.height;
			  }
			  var objectsToExclude = [cartographic];
			  if (opts.asyn){
				  Cesium.sampleTerrainMostDetailed(viewer.scene.terrainProvider,objectsToExclude).then(function(samples) {
					    var heightTerrain;
			            var clampedCart = samples[0];
			            if (Cesium.defined(clampedCart) && Cesium.defined(clampedCart.height)) {
			                heightTerrain = clampedCart.height;
			    			if(heightTerrain<0){
			    				console.log(heightTerrain);
			    			}
			            } else {
			                heightTerrain = viewer.scene.globe.getHeight(cartographic);
			            }
			            if (opts.calback) opts.calback(heightTerrain);
				  })
			  }else{
			        var heightTerrain = viewer.scene.globe.getHeight(cartographic);
			        if (Cesium.defined(heightTerrain) && heightTerrain > -1000) {
			            return heightTerrain;
			        }
			  }
		}	
	}
	return 0;
}


VFG.Util.getCurrentExtent=function(viewer) {
    // 范围对象
    var extent = {};

    // 得到当前三维场景
    var scene = viewer.scene;

    // 得到当前三维场景的椭球体
    var ellipsoid = scene.globe.ellipsoid;
    var canvas = scene.canvas;

    // canvas左上角
    var car3_lt = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, 0), ellipsoid);

    // canvas右下角
    var car3_rb = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width, canvas.height), ellipsoid);

    // 当canvas左上角和右下角全部在椭球体上
    if (car3_lt && car3_rb) {
        var carto_lt = ellipsoid.cartesianToCartographic(car3_lt);
        var carto_rb = ellipsoid.cartesianToCartographic(car3_rb);
        extent.xmin = Cesium.Math.toDegrees(carto_lt.longitude);
        extent.ymax = Cesium.Math.toDegrees(carto_lt.latitude);
        extent.xmax = Cesium.Math.toDegrees(carto_rb.longitude);
        extent.ymin = Cesium.Math.toDegrees(carto_rb.latitude);
    }

    // 当canvas左上角不在但右下角在椭球体上
    else if (!car3_lt && car3_rb) {
        var car3_lt2 = null;
        var yIndex = 0;
        do {
            // 这里每次10像素递加，一是10像素相差不大，二是为了提高程序运行效率
            yIndex <= canvas.height ? yIndex += 10 : canvas.height;
            car3_lt2 = viewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, yIndex), ellipsoid);
        } while (!car3_lt2);
        var carto_lt2 = ellipsoid.cartesianToCartographic(car3_lt2);
        var carto_rb2 = ellipsoid.cartesianToCartographic(car3_rb);
        extent.xmin = Cesium.Math.toDegrees(carto_lt2.longitude);
        extent.ymax = Cesium.Math.toDegrees(carto_lt2.latitude);
        extent.xmax = Cesium.Math.toDegrees(carto_rb2.longitude);
        extent.ymin = Cesium.Math.toDegrees(carto_rb2.latitude);
    }

    // 获取高度
    extent.height = Math.ceil(viewer.camera.positionCartographic.height);
    return extent;
}

/**
 * viewer:viewer
 * cameraPosition:起点
 * position:目标
 */
VFG.Util.getHeadingPitchRoll = function (viewer,cameraPosition,position) {
	var _this=this;
    var e = cameraPosition,
    t = position,
    i = Cesium.Cartesian3.normalize(Cesium.Cartesian3.subtract(t, e, new Cesium.Cartesian3), new Cesium.Cartesian3),
    a = Cesium.Cartesian3.normalize(e, new Cesium.Cartesian3),
    n = new Cesium.Camera(viewer.scene);
    n.position = e,
    n.direction = i,
    n.up = a,
    i = n.directionWC,
    a = n.upWC;
    var r = n.rightWC,
    o = new Cesium.Cartesian3,
    l = new Cesium.Matrix3,
    u = new Cesium.Quaternion;
    r = Cesium.Cartesian3.negate(r, o);
    var d = l;
    Cesium.Matrix3.setColumn(d, 0, r, d),
    Cesium.Matrix3.setColumn(d, 1, a, d),
    Cesium.Matrix3.setColumn(d, 2, i, d);
    var c = Cesium.Quaternion.fromRotationMatrix(d, u);
    var hpr = Cesium.HeadingPitchRoll.fromQuaternion(c);
    
    //return hpr;
    // 得到角度
/*    var heading = Cesium.Math.toDegrees(hpr.heading);
    var pitch = Cesium.Math.toDegrees(hpr.pitch);
    var roll = Cesium.Math.toDegrees(hpr.roll);*/
    return hpr
};

/**
 * Turf多边形
 */
VFG.Util.getTurfPolygon = function (points) {
	var area=[];
	for(var i=0;i<points.length;i++){
		var point=[];
		point[0]=points[i].x;
		point[1]=points[i].y;
		area.push(point);
	}
	
	var point=[];
	point[0]=points[0].x;
	point[1]=points[0].y;
	area.push(point);
	return turf.polygon([area]);
}

/**
 * Turf点
 */
VFG.Util.getTurfPoint = function (point) {
	return turf.point([point.x*1, point.y*1]);
}

/**
 * 点是否在多边形内部
 */
VFG.Util.booleanPointInPolygon = function (polygon,point) {
	return turf.booleanPointInPolygon(point,polygon);
}


